本系列文章已重新編修,並在加入部分 ES6 新篇章後集結成書,有興趣的朋友可至天瓏書局選購,感謝大家支持。
購書連結 https://www.tenlong.com.tw/products/9789864344130
讓我們再次重新認識 JavaScript!
花了好幾天的時間,「重新認識 JavaScript: JS 基礎篇」終於告一段落了。
如果讀者跟著我一路看到這裡,相信各位對 JavaScript 這門程式語言已經有了基本的理解。
從今天開始,我們要進入「前端工程師的主戰場:瀏覽器裡的 JavaScript」的部分囉。
在許多的網頁前端教學或是文章書籍當中,你可能常常聽到這樣的說法:「HTML、CSS 與 JavaScript 是網頁前端三大要素」
這樣的說法基本上沒有錯。
那麼,如果你跟我當年學 JavaScript 也有一樣的疑問:變數、型別、物件、迴圈、流程控制、函式... 表面上看似基礎都學會了,但...
「我還是不知道怎麼透過 JavaScript 在網頁上輸出 "Hello World!" 啊!」
那麼相信看完今天的分享,我保證你一定可以透過 JavaScript 在網頁上輸出 "Hello World!" (咦)
嚴格來說,JavaScript (或者說 ECMAScript 標準) 並沒有提供網頁的操作方法。
事實上,前端開發者在網頁的操作方法都是由 JavaScript 的執行平台,也就是「瀏覽器」提供的。 這些操作方法基本上會分別由這兩種物件所擁有:「BOM」與「DOM」。
所以廣泛來說,在瀏覽器上的 JavaScript 實際上包含了:
以上這三個部分。
由於「BOM」與「DOM」是由瀏覽器執行環境所提供。
換句話說,在 node 環境下的 JavaScript 就不會有這兩個部分。
前端開發者就是透過 JavaScript 去呼叫 BOM 與 DOM 提供的 API,進一步透過它們去控制瀏覽器的行為與網頁的內容。
那麼接下來我們就來介紹「BOM」與「DOM」。
BOM (Browser Object Model,瀏覽器物件模型),是瀏覽器所有功能的核心,與網頁的內容無關。
在早期沒有制定標準規範的時候,各家瀏覽器廠商幾乎各自在自家瀏覽器上實作功能,非常混亂。 直到最近幾年, W3C 把各家瀏覽器都有實作的部分,以及確定已經(或未來會) 加入的功能,統一集合起來納入了 HTML5 的標準中,這也就是我們現在看到的 BOM API 的實作。
BOM 也有人非正式地稱它為 「Level 0 DOM」。 因為它在 DOM level 1 標準前就已存在,而不是真的有文件去規範這些,所以「Level 0 DOM」與「BOM」兩者實際上指的是同一個東西。
window
物件BOM 的核心是 window
物件。
而 window
物件提供的屬性主要為 document
、location
、navigator
、screen
、history
以及 frames
。
在瀏覽器裡的 window
物件扮演著兩種角色:
全域物件的部分我們之前已經談過,凡是在「全域作用範圍」內宣告的變數、物件、函式等,都會自動變成「全域物件」的屬性。 通常這樣的變數,我們會稱它們叫做「全域變數」,可以透過 window.xxx
的方式取得它們。
var a = 10;
console.log( window.a ); // 10
除此之外,在「全域作用範圍」宣告的全域變數還有一個特性,就是無法使用 delete
關鍵字來移除:
var a = 10;
console.log( window.a ); // 10
delete window.a; // false
console.log( window.a ); // 10
但若是直接透過指定 window
物件的屬性則可以:
window.a = 10;
console.log( window.a ); // 10
delete window.a; // true
console.log( window.a ); // undefined
現在我們已經知道了「全域物件」是怎麼回事了,那麼 window
物件扮演的另一個角色,「用來與瀏覽器溝通的窗口」又是什麼意思呢?
先來個最常見的例子: alert()
「警告對話框」:
(alert on Chrome)
我想不管是不是剛接觸 JavaScript 的朋友,對 alert
應該都不陌生,alert
的完整語法其實是這樣:
window.alert(message);
如同我們所熟知的全域變數一樣,window
物件下的成員,window
是可以省略不打的。
一行程式碼就可以生成一個對話框,很神奇吧?
而這就是瀏覽器環境的 BOM 提供給 JavaScript 控制的功能之一。
類似的對話框還有用來提供「確定/取消」的 window.confirm()
window.confirm ,以及開放式問答的 window.prompt()
window.prompt 對話框。
當然 BOM 提供的 API 很多,包含開啟/關閉視窗,改變視窗大小,計時器與取得網址等等。 這些在之後的文章當中還會再詳細解說。
DOM (Document Object Model,文件物件模型),是一個將 HTML 文件以樹狀的結構來表示的模型,而組合起來的樹狀圖,我們稱之為「DOM Tree」。
簡單來說,我們把 HTML 每個節點的關係攤來看,就好像是一棵樹一樣。
假設我們有一個基本的 HTML 如下:
<html>
<head>
<title>一個簡單的網頁</title>
</head>
<body>
<h1>這是標題</h1>
<p>這是一個<i>簡單</i>的網頁</p>
</body>
</html>
在最根部的地方,就是 document
,就是 BOM 圖中 window
下面的那個。
往下可以延伸出一個個的 HTML 標籤,一個節點就是一個標籤,往下又可以再延伸出「文本節點」與「屬性的節點」。
而 DOM API 就是定義了讓 JavaScript 可以存取、改變 HTML 架構、樣式和內容的方法,甚至是對節點綁定的事件。
JavaScript 就是透過 DOM 提供的 API 來對 HTML 做存取與操作。
前面介紹 BOM 時,我們已經知道 DOM 的 document
其實也是 window
物件的子物件之一。
而「DOM」 與「BOM」最大的區別在於:
「BOM」完全依賴於瀏覽器廠商實作本身無標準規範,而「DOM」有著 W3C 所制定的標準來規範。
想要透過 DOM API 取得節點,透過 JavaScript 可以這樣寫:
// 根據傳入的值,找到 DOM 中 id 為 'xxx' 的元素。
document.getElementById('xxx');
// 針對給定的 tag 名稱,回傳所有符合條件的 NodeList 物件 [註1]
document.getElementsByTagName('xxx');
// 針對給定的 class 名稱,回傳所有符合條件的 NodeList 物件。
document.getElementsByClassName('xxx');
// 針對給定的 Selector 條件,回傳第一個 或 所有符合條件的 NodeList。
document.querySelector('xxx');
document.querySelectorAll('xxx');
而透過 DOM API 選取出來的節點,我們可以透過操作 textContent
屬性來變更它的文字。
假設有一個 HTML 節點:
<h1 id="greet"></h1>
再來我們就可以先透過 document.querySelector()
方法來取得節點,然後修改 textContent
屬性:
<script>
document.querySelector('#greet').textContent = 'Hello World!'
</script>
看到這裡,恭喜你已經可以透過 JavaScript 在網頁上輸出 "Hello World!" 囉!
在後續的內容中,我們會繼續來介紹各種操作網頁的 DOM/BOM API。
畢竟對前端工程師來說,搞懂怎麼與瀏覽器打交道、怎麼操作網頁內容,就是做好 WebUI 最重要的基礎。
Node.childNodes
屬性或 document.querySelectorAll()
等方法取得。 NodeList 雖然有著與陣列相似的特性,但不是陣列,所以也不會有陣列相關的 method 可以使用 (如 map
、filter
等)。“JavaScript到底怎么在网页上显示出‘hello world’”,这个问题真的一直困扰我,感谢分享!
大大:
JS Bin on jsbin.com 這個範例的鏈結因為 jsbin 的系統有更新,所以無法觀看了。
可以了,謝謝:)